package com.zhny.aiot.gdsfj.plugin.device;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhny.aiot.gdsfj.plugin.model.*;
import com.zhny.aiot.plugin.ICenterFacilities;
import com.zhny.aiot.plugin.IDeviceFactory;
import com.zhny.aiot.plugin.core.model.IRequestMessage;
import com.zhny.aiot.plugin.core.utils.MessageUtils;
import com.zhny.aiot.plugin.modbus.ModemEngine;
import com.zhny.aiot.plugin.modbus.device.ModemConfig;
import com.zhny.aiot.plugin.modbus.device.ModemDevice;
import com.zhny.aiot.plugin.modbus.handler.model.IModemRequestMessage;
import com.zhny.aiot.plugin.modbus.handler.model.ModemRequestMessage;
import com.zhny.aiot.plugin.modbus.handler.model.ModemResponseMessage;
import com.zhny.aiot.plugin.model.*;
import com.google.common.collect.ImmutableMap;

import java.util.Map;

public class FertilizerDevice extends ModemDevice<FertilizerStoreEntry> {
    private final Map<String, FerilizerParamer> CommandOperations;
    public FertilizerDevice(ModemEngine engine,
                            IDeviceFactory<ModemConfig> factory,
                            ICenterFacilities centerFacilities,
                            DeviceEntity entity) {
        super (engine, factory, centerFacilities,entity);
        CommandOperations =  new ImmutableMap.Builder<String, FerilizerParamer>()
                .put("openPump", new FerilizerParamer((short) 5,24,65280))
                .put("closePump", new FerilizerParamer((short)5,24,0))
                .put("setMainFlowValue", new FerilizerParamer((short)5,0x4b,-1))
                .put("openSetMainFlow", new FerilizerParamer((short)5,0x40,65280))
                .put("closeSetMainFlow", new FerilizerParamer((short)5,0x40,0))
                .put("openChannelA", new FerilizerParamer((short)5,25,65280))
                .put("closeChannelA", new FerilizerParamer((short)5,25,0))
                .put("openChannelB", new FerilizerParamer((short)5,26,65280))
                .put("closeChannelB", new FerilizerParamer((short)5,26,0))
                .put("openChannelC", new FerilizerParamer((short)5,27,65280))
                .put("closeChannelC", new FerilizerParamer((short)5,27,0))
                .put("openChannelD", new FerilizerParamer((short)5,58,65280))
                .put("closeChannelD", new FerilizerParamer((short)5,58,0))
                .put("openChannelE", new FerilizerParamer((short)5,0x3c,65280))
                .put("closeChannelE", new FerilizerParamer((short)5,0x3c,0))
                .put("openChannelF", new FerilizerParamer((short)5,0x3e,65280))
                .put("closeChannelF", new FerilizerParamer((short)5,0x3e,0))
                .put("openBucketA", new FerilizerParamer((short)5,54,65280))
                .put("closeBucketA",new FerilizerParamer((short)5,54,0))
                .put("openBucketB",new FerilizerParamer((short)5,55,65280))
                .put("closeBucketB",new FerilizerParamer((short)5,55,0))
                .put("openBucketC",new FerilizerParamer((short)5,56,65280))
                .put("closeBucketC",new FerilizerParamer((short)5,56,0))
                .put("openBucketD",new FerilizerParamer((short)5,57,65280))
                .put("closeBucketD",new FerilizerParamer((short)5,57,0))
                .put("openBucketE",new FerilizerParamer((short)5,0x5d,65280))
                .put("closeBucketE",new FerilizerParamer((short)5,0x5d,0))
                .put("openBucketF",new FerilizerParamer((short)5,0x5e,65280))
                .put("closeBucketF",new FerilizerParamer((short)5,0x5e,0))
                .put("readPumpState", new FerilizerParamer((short)2,0,1))
                .put("readMain",new FerilizerParamer((short)3,54,23)).build();
    }


    @Override
    public void onDecoder(ModemResponseMessage modemResponseMessage) {
        logger.info("---start decoder fertilizer message---");
        FertilizerResultModel resultModel = null;
        int function = modemResponseMessage.getFunction();
        switch (function){
            case 5:
                resultModel = new FertilizerCoilResultModel(modemResponseMessage,this);
                break;
            case 3:
                resultModel = new FerilizerTableResultModel(modemResponseMessage,this);
                break;
            case 2:
                resultModel= new FerilizerDiscreteResultModel(modemResponseMessage,this);
                break;
            default:
                MessageEntry messageEntry = MessageUtils.createMessageEntry(getId());
                messageEntry.setType (MessageType.ERROR);
                messageEntry.setData ("response no support !");
                this.nofity (messageEntry);
                break;
        }
        resultModel.onHandler();
    }

    @Override
    public IRequestMessage getCommand(TaskEntity taskEntity){
        logger.error ("水肥控制指令任务：方法：{}，参数：{}",taskEntity.getMethodName(),taskEntity.getParams());
        MessageEntry entry= MessageUtils.createMessageEntry(this.getId());
        entry.getProperties().put("task_name", taskEntity.getMethodName());
        entry.setType(MessageType.OPERATION);
        FerilizerParamer command = CommandOperations.get(taskEntity.getMethodName());
        if(command == null){
            entry.setType (MessageType.ERROR);
            entry.setData (String.format("factory[%s] no support command [%s]",getTypeId (),taskEntity.getMethodName ()));
            this.nofity (entry);
            return null;
        }
        if(command.getData() < 0){ //需要传参
            FerilizerParam param = null;
            String taskParam = taskEntity.getParams();
            ObjectMapper mapper = new ObjectMapper();
            try{
                param = mapper.readValue(taskParam,FerilizerParam.class);
            }catch (Exception e){
                logger.error ("Parse param error !");
                return  null;
            }
            String value = param.getValue();
            if(value.contains(".")){ //小数用浮点  数据转换
                return new ModbusFloatRequestMessage(Integer.parseInt(this.getConfig().getAddress()),command.getCode(),command.getRegisterAddress(),Float.parseFloat(value));
            }else{//整形
                return new ModemRequestMessage(Integer.parseInt(this.getConfig().getAddress()),command.getCode(),command.getRegisterAddress(),Integer.parseInt(value));
            }
        }else {
            return new ModemRequestMessage(Integer.parseInt(this.getConfig().getAddress()),command.getCode(),command.getRegisterAddress(),command.getData());
        }
    }

    @Override
    protected void disposable() {

    }
}
